/** \file    read_enum.h
  * \brief   Simplifies construction of enumeration variable readers.
  * \date    2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/include/read_enum.h,v 1.4 2004/10/05 17:59:22 cscom1r4 Exp $
  */

#ifndef _read_enum_h_
#define _read_enum_h_

#include <string>
#include <iostream>

template <typename E>
std::istream & read_enum(std::istream & s, E & e, const char * const * names, size_t name_count)
{
	std::string val;
	s >> val;
	for (int n = 0; n != name_count; ++n) {
		if (val == names[n]) {
			e = E(n);
			return s;
		}
	}
	s.setstate(std::ios::failbit);
	return s;
}

///the same for names list finalized by 0
template <typename E>
std::istream & read_enum(std::istream & s, E & e, const char * const * names)
{
	std::string val;
	s >> val;
	for (int n = 0; *names; ++names, ++n) {
		if (val == *names) {
			e = E(n);
			return s;
		}
	}
	s.setstate(std::ios::failbit);
	return s;
}

#define DECLARE_ENUM_IO_OPERATORS(type) \
	std::ostream & operator << (std::ostream & s, type a); \
	std::istream & operator >> (std::istream & s, type & a);

#define DEFINE_ENUM_IO_OPERATORS(type, strvec) \
	std::ostream & operator << (std::ostream & s, type a) \
		{ return s << strvec[a]; } \
	std::istream & operator >> (std::istream & s, type & a) \
		{ return read_enum(s, a, strvec); }

#define DEFINE_INLINE_ENUM_IO_OPERATORS(type, strvec) \
	inline std::ostream & operator << (std::ostream & s, type a) \
		{ return s << strvec[a]; } \
	inline std::istream & operator >> (std::istream & s, type & a) \
		{ return read_enum(s, a, strvec); }

#endif //_read_enum_h_
